package myoa

import myoa.domain.ExpenseGroupStatus
import myoa.domain.RoleName
import myoa.excel.ExcelSheetName
import myoa.tool.SessionTool
import myoa.tool.ShiroTool
import myoa.tool.StringTool

class ExpenseGroupController {
    ExcelImpService excelImpService
    FileStoreService fileStoreService

    def beforeInterceptor = [action: this.&readOnly, only: ['edit', 'update', 'delete']]

    //private will not display in Role page
    private readOnly() {
        def group = ExpenseGroup.get(params.id)
        if (group.status != ExpenseGroupStatus.New) {
            flash.message = message(code: 'expense.read.only')
            redirect(action: 'show', id: params.id)
            return false //false=终止，不在继续进入后续action
        }
    }

//----------level 1 by first access control: auth----------
    def create() {

    }

    def save() {
        ExpenseGroup e = new ExpenseGroup(params)
        e.status = ExpenseGroupStatus.New
        e.traceCreate()
        if (e.save()) {
            redirect(action: 'list')
        } else {
            flash.message = message(code: 'default.save.failed')
            redirect(action: 'create')
        }
    }

    def upload() {

    }

    def uploadDo() {
        FileStore fs = fileStoreService.upload()
        List<Map> EXPENSE_FULL = excelImpService.imp(fs.id, ExcelSheetName.EXPENSE_FULL)
        int successCount = 0
        EXPENSE_FULL.each {
            it.eDetail_payDate = StringTool.parseExcelDate(it.eDetail_payDate)
            ExpenseDetail eDetail = new ExpenseDetail()
            eDetail.payDate = it.eDetail_payDate
            eDetail.payAmount = it.eDetail_payAmount
            eDetail.payFor = it.eDetail_payFor

            ExpenseGroup eGroup = ExpenseGroup.findWhere(name: it.eGroup_name, createdBy: SessionTool.loginUser)
            if (!eGroup) {
                eGroup = new ExpenseGroup()
                eGroup.name = it.eGroup_name
                eGroup.type = it.eGroup_type
                eGroup.status = ExpenseGroupStatus.New
                eGroup.traceCreate()
                eGroup.save()
            }
            eDetail.expenseGroup = eGroup
            if (eDetail.save()) {
                successCount++
            }
        }
        flash.message = "${successCount} of ${EXPENSE_FULL.size()} expense detail insert success"
        redirect(action: 'list')
    }

    def approve(Long id) {
        def eg = ExpenseGroup.get(id)
        if (eg.status != ExpenseGroupStatus.New) {
            flash.message = message(code: 'expense.approve.status.error')
        } else {
            eg.approvedBy = SessionTool.loginUser
            eg.approvedDate = new Date()
            eg.status = ExpenseGroupStatus.Approved
            eg.traceUpdate()
            if (eg.save()) {
                flash.message = message(code: 'expense.approve.success',
                        args: [eg.name, eg.createdBy.name, eg.approvedBy.name])
            } else {
                flash.message = message(code: 'default.save.failed')
            }
        }
        redirect(action: 'show', id: id)
    }

    def writeoff(Long id) {
        def eg = ExpenseGroup.get(id)
        if (eg.status != ExpenseGroupStatus.Approved) {
            flash.message = message(code: 'expense.writeoff.status.error')
        } else {
            eg.writeoffBy = SessionTool.loginUser
            eg.writeoffDate = new Date()
            eg.status = ExpenseGroupStatus.WriteOff
            eg.traceUpdate()
            if (eg.save()) {
                flash.message = message(code: 'expense.writeoff.success',
                        args: [eg.name, eg.createdBy.name, eg.writeoffBy.name])
            } else {
                flash.message = message(code: 'default.save.failed')
            }
        }
        redirect(action: 'show', id: id)
    }

//----------level 2 by following access control----------
    def show(Long id) {
        ExpenseGroup eGroup = ExpenseGroup.read(id)
        int sumPayAmount = 0
        if (eGroup.expenseDetails.size() != 0) {
            sumPayAmount = (int) eGroup.expenseDetails.getAt('payAmount').sum()
        }
        [expenseGroup: eGroup, sumPayAmount: sumPayAmount]
    }

    def edit(Long id) {
        [expenseGroup: ExpenseGroup.read(id)]
    }

    def update(Long id) {
        ExpenseGroup e = ExpenseGroup.get(id)
        e.properties = params
        e.traceUpdate()

        if (e.save()) {
            flash.message = message(code: 'default.save.success')
            redirect(action: 'show', id: id)
        } else {
            flash.message = message(code: 'default.save.failed')
            render(view: "edit", model: [expenseGroup: e])
        }
    }

    def delete(Long id) {
        ExpenseGroup e = ExpenseGroup.get(id)
        e.delete()
        flash.message = message(code: 'default.delete.success', args: [e.name])
        redirect(action: 'list')
    }

//----------level 3 by action inner----------
    def list() {
        User owner = SessionTool.loginUser
        params.max = StringTool.paginateMax(params.max)
        def egs = []  //todo empty return... any optimize?
        if (ShiroTool.hasOneRoleOf(RoleName.ACC, RoleName.MGR) || ShiroTool.isRoot()) {
            egs = ExpenseGroup.findAll(params)
        } else if (ShiroTool.hasOneRoleOf(RoleName.EMP)) {
            egs = ExpenseGroup.findAllByCreatedBy(owner, params)
        }
        [expenseGroups: egs, total: egs.size()]
    }
}
